package org.example.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;

import java.util.concurrent.*;

@Slf4j
@EnableAsync
@EnableScheduling
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties({ThreadPoolConfigProperties.class, PanSouProperties.class})
public class ThreadPoolConfig {

    private final PanSouProperties panSouProperties;

    @Bean
    @ConditionalOnMissingBean(ThreadPoolExecutor.class)
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 实例化策略
        RejectedExecutionHandler handler;
        switch (properties.getPolicy()){
            case "AbortPolicy":
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
            case "DiscardPolicy":
                handler = new ThreadPoolExecutor.DiscardPolicy();
                break;
            case "DiscardOldestPolicy":
                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;
            case "CallerRunsPolicy":
                handler = new ThreadPoolExecutor.CallerRunsPolicy();
                break;
            default:
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
        }
        // 创建线程池
        return new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(properties.getBlockQueueSize()),
                Executors.defaultThreadFactory(),
                handler);
    }

    /**
     * 异步插件工作池调度器
     */
    @Bean("asyncPluginScheduler")
    public Scheduler asyncPluginScheduler() {
        return Schedulers.fromExecutor(
            Executors.newFixedThreadPool(
                panSouProperties.getAsync().getMaxWorkers(),
                r -> {
                    Thread t = new Thread(r, "async-plugin-");
                    t.setDaemon(true);
                    return t;
                }
            )
        );
    }

    /**
     * 缓存操作调度器
     */
    @Bean("cacheScheduler")
    public Scheduler cacheScheduler() {
        return Schedulers.fromExecutor(
            Executors.newFixedThreadPool(
                Math.max(2, Runtime.getRuntime().availableProcessors()),
                r -> {
                    Thread t = new Thread(r, "cache-worker-");
                    t.setDaemon(true);
                    return t;
                }
            )
        );
    }

    /**
     * 搜索服务调度器
     */
    @Bean("searchScheduler")
    public Scheduler searchScheduler() {
        return Schedulers.fromExecutor(
            Executors.newCachedThreadPool(
                r -> {
                    Thread t = new Thread(r, "search-worker-");
                    t.setDaemon(true);
                    return t;
                }
            )
        );
    }
}
